package com.db.httpserver;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;

public class MadClient implements Runnable {
	static final int CROWD_VOLUME = 1000;
	static final int LIFE_TIME = 10000;
	static final int WAIT_TIME = 1;
	static final int TIMEOUT = 5000;
	static int failCount = 0;

	InetAddress address;
	int port;
	volatile boolean working = true;
	
	public MadClient(InetAddress address, int port) {
		this.address = address;
		this.port = port;
	}
	@Override
	public void run() {
		Socket socket = null;
		PrintWriter writer = null;
		BufferedReader reader = null;
		while (working) {
			try {
				socket = new Socket(address, port);
				socket.setSoTimeout(TIMEOUT);
				writer = new PrintWriter(socket.getOutputStream());
				reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			} catch (IOException e) {
				System.out.println("IOException when socket opening: " + e.getMessage());
				if (socket != null)
					try {
						socket.close();
					} catch (IOException e1) {
						System.out.println("IOException when socket closing: " + e1.getMessage());
					}
				continue;
			}
			
			writer.printf("GET %s HTTP/1.1\r\nHost:%s\r\n", "/", address.getHostAddress() + ":" + port);
			writer.flush();
			try {
				do {
					//System.out.println("Response from server: " + reader.readLine());
					reader.readLine();
				} while (socket.getInputStream().available() != 0);
				
			} catch (SocketTimeoutException e1) {
				System.out.println("SocketTimeoutException: " + e1.getMessage());	
				failCount++;
				
			} catch (IOException e1) {
				System.out.println("IOException when data reading: " + e1.getMessage());
			}
			try {
				Thread.sleep(WAIT_TIME);
			} catch (InterruptedException e) {}
		}
		
		try {
			if (socket != null)
				socket.close();
		} catch (IOException e) {
			System.out.println("IOException when socket closing: " + e.getMessage());
		}
		
		//System.out.println("I've stopped");		
	}
	
	public void shutdown() {
		working = false;
	}
	
    public static void main(String[] args) throws Exception {
        int port = -1;
        if (args.length > 0) {
            port = Integer.parseInt(args[0]);
        }
        
        List<MadClient> madclientCrowd = new ArrayList<MadClient>(CROWD_VOLUME);
        
        System.out.println("Start mad clients invasion");
        for (int i=0; i<CROWD_VOLUME; i++)
        {
        	MadClient client = new MadClient(InetAddress.getLoopbackAddress(), port);
        	madclientCrowd.add(client);
        	new Thread(client).start();
        }
        
        Thread.sleep(LIFE_TIME);

        for (int i=0; i<CROWD_VOLUME; i++)
        {
        	madclientCrowd.get(i).shutdown();
        }
        
        System.out.printf("Occurred %d fails with %d clients, %d requests from one client per sec and %d timeout%n", 
        		failCount, CROWD_VOLUME, 1000 / WAIT_TIME, TIMEOUT);
    }
}
